/**
 * 
 */
package com.iss.card.mapv2;

import java.util.List;
import java.util.Locale;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.util.Log;

import com.baidu.location.BDLocation;
import com.iss.card.common.CommonValue;
import com.iss.card.model.CityDataManager;
import com.iss.card.view.model.CityBean;

/**
 * @author dtdh
 * 
 */
public class MyLocationManager {
	private final static String TAG = MyLocationManager.class.getSimpleName();
	private final static String GOOGLE_MAP_WEBAPI_GEOCODE_LOCATION = "http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f&sensor=true&oe=utf8&language=zh-CN";
	private Context mContext;
	private static MyLocationManager sInstance;
	private BDLocation mCurrentLocation;

	private MyLocationManager() {

	}

	public synchronized static MyLocationManager instance() {
		if (sInstance == null) {
			sInstance = new MyLocationManager();
		}
		return sInstance;
	}

	/**
	 * set context
	 * 
	 * @param ct
	 */
	public void initialize(Context ct) {
		mContext = ct;
	}

	public void setCurrentLocationPosition(BDLocation l) {
		mCurrentLocation = l;
	}

	public String getCurrentCityName() {
		if (mCurrentLocation == null) {
			return CommonValue.STR_EMPTY;
		}

		if (CommonValue.STR_EMPTY.equals(mCurrentLocation.getAddrStr())) {
			return geoCodeLocation(getCurrentPosition());
		}
		Log.d(TAG, "getCurrentCityName: " + mCurrentLocation.getCity());
		return mCurrentLocation.getCity();
	}

	public CityBean getCurrentLocatedCityByDevice() {
		Log.d(TAG, "getCurrentLocatedCityByDevice");
		return CityDataManager.instance().findCityInfoByCityName(
				getCurrentCityName());
	}

	public Location getCurrentPosition() {
		// current location.
		Location cur = new Location("");
		if (mCurrentLocation != null) {
			cur.setLatitude(mCurrentLocation.getLatitude());
			cur.setLongitude(mCurrentLocation.getLongitude());
		}
		return cur;
	}

	/**
	 * destroy current instance.
	 */
	public void destroy() {
		if (sInstance != null) {
			sInstance = null;
		}
	}

	// get address by location.
	private List<Address> getAddressbyLocation(Location location) {
		List<Address> result = null;
		try {

			if (location != null) {
				Geocoder gc = new Geocoder(mContext, Locale.getDefault());
				result = gc.getFromLocation(location.getLatitude(),
						location.getLongitude(), 1);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	private String geoCodeLocation(Location loc) {
		List<Address> address = getAddressbyLocation(loc);
		if (address == null || address.size() == 0) {
			return parseJsonResponseData(requestGeoCodeWebAPI(
					loc.getLatitude(), loc.getLongitude()));
		} else {
			for (Address a : address) {
				Log.d(TAG, "getCurrentCity: " + a.getLocality());
			}
		}

		return address.get(0).getLocality();
	}

	private String requestGeoCodeWebAPI(double latitude, double longitude) {
		String url = String.format(GOOGLE_MAP_WEBAPI_GEOCODE_LOCATION,
				latitude, longitude);
		Log.d(TAG, "requestGeoCodeWebAPI: url=[" + url + "]");
		HttpGet get = new HttpGet(url);
		String strResult = "";
		try {
			HttpParams httpParameters = new BasicHttpParams();
			HttpConnectionParams.setConnectionTimeout(httpParameters, 3000);
			HttpClient httpClient = new DefaultHttpClient(httpParameters);

			HttpResponse httpResponse = null;
			httpResponse = httpClient.execute(get);

			if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				strResult = EntityUtils.toString(httpResponse.getEntity());
			}
		} catch (Exception e) {
			return CommonValue.STR_EMPTY;
		}
		// Log.d(TAG, "requestGeoCodeWebAPI: [" + strResult + "]");
		return strResult;
	}

	private String parseJsonResponseData(String str) {
		Log.d(TAG, "parseJsonResponseData=" + str);
		try {
			JSONArray addresses = new JSONObject(str).getJSONArray("results")
					.optJSONObject(0).getJSONArray("address_components");
			final int size = addresses.length();
			for (int i = 0; i < size; ++i) {
				JSONObject obj = addresses.optJSONObject(i);
				String type = obj.getJSONArray("types").getString(0);
				if ("route".equals(type)) { // route.
				} else if ("sublocality".equals(type)) { // area.
				} else if ("locality".equals(type)) { // city.
					return obj.getString("long_name");
				} else if ("administrative_area_level_1".equals(type)) { // province.
				} else if ("country".equals(type)) { // country.
				}
			}
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return CommonValue.STR_EMPTY;
	}
}
